<?php
namespace App\Http\Classes;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/5/2 0002
 * Time: 上午 9:26
 */
class Head
{
    private $src;
    private $data;
    private $name;
    private $dst180;
    private $dst50;
    private $dst30;
    private $url180;
    private $url50;
    private $url30;
    private $type;
    private $extension;
    private $msg;
    private $host;
    private $code;

    function __construct($name,$src,$type,$data)
    {
        $this -> setName($name);
        $this -> setHost();
        $this -> setSrc($src,$type);
        $this -> setData($data);
        if($this->src != null){
            $this -> crop($this->src,$this->data);
        }
        else{
            $this -> code = 404;
            $this -> msg = 'Original image not exisit';
        }
    }

    private function setHost(){
        $this -> host = 'http://'.$_SERVER['HTTP_HOST'].'/';
    }

    private function setUrl(){
        $this -> url180 = $this -> host . $this -> dst180;
        $this -> url50 = $this -> host . $this -> dst50;
        $this -> url30 = $this -> host .$this -> dst30;
    }

    private function updateUser(){
        $this -> setUrl();
        $user = new User($_COOKIE['user_id']);
        $user = $user->updateHead($this->url50,$this->url180,$this->url30);
        if($user){
            $this -> code = 200;
            $this -> msg = 'Head image saved and update success!';
        }
        else{
            $this -> code = 304;
            $this -> msg = 'Head image saved but update error!';
        }
    }

    private function setSrc($src,$type){
        if (!empty($src) && !empty($type)){
            if ($type) {
                $this -> src = $src;
                $this -> type = $type;
                $this -> extension = image_type_to_extension($type);
                $this -> setDst();
            }
        }
    }

    private function setData($data){
        if (!empty($data)){
            $this -> data = json_decode(stripslashes($data));
        }
    }

    private function setFile($file){
        $errorCode = $file['error'];
        if ($errorCode === UPLOAD_ERR_OK){
            $type = $file['type'];
            if($type == 'image/jpeg'){
                $type = IMAGETYPE_JPEG;
            }
            else if ($type == 'image/png'){
                $type = IMAGETYPE_PNG;
            }
            else if ($type == 'image/gif'){
                $type = IMAGETYPE_GIF;
            }
            else{
                $type = false;
            }

            if ($type){
                $extension = image_type_to_extension($type);

                $src = 'weiboimg/face/original/'.$this->name.$extension;

                if ($type == IMAGETYPE_GIF || $type == IMAGETYPE_JPEG || $type == IMAGETYPE_PNG){

                    if (file_exists($src)){
                        unlink($src);
                    }

                    $result = move_uploaded_file($file['tmp_name'],$src);

                    if ($result){
                        $this -> src = $src;
                        $this -> type = $type;
                        $this -> extension = $extension;
                        $this -> setDst();
                    } else{
                        $this -> code = 304;
                        $this -> msg = 'Failed to save file';
                    }
                } else{
                    $this -> msg = 'Please upload image with the following types: JPG, PNG, GIF';
                }
            } else{
                $this -> msg = 'Please upload image file';
            }
        } else{
            $this -> msg = $this -> codeToMessage($errorCode);
        }
    }

    private function setName($name){
        $this -> name = $name;
    }

    private function setDst(){
        $root = 'weiboimg/face/';
        $this -> dst180 = $root.'avatar_180/'.$this->name.$this->extension;
        $this -> dst50 = $root.'avatar_50/'.$this->name.$this->extension;
        $this -> dst30 = $root.'avatar_30/'.$this->name.$this->extension;
    }

    private function crop($src,$data){
        if (!empty($src) && !empty($data)){
            $size = getimagesize($src);
            $this -> type = $size[2];
            $src_img = null;
            switch ($this -> type) {
                case IMAGETYPE_GIF:
                    $src_img = imagecreatefromgif($src);
                    break;
                case IMAGETYPE_JPEG:
                    $src_img = imagecreatefromjpeg($src);
                    break;
                case IMAGETYPE_PNG:
                    $src_img = imagecreatefrompng($src);
                    break;
            }

            if ($src_img == null){
                $this -> code = 403;
                $this -> msg = "Failed to read the image file";
                return;
            }

            $size = getimagesize($src);
            $size_w = $size[0];
            $size_h = $size[1];

            $src_img_w = $size_w;
            $src_img_h = $size_h;

            $degrees = $data -> rotate;

            if (is_numeric($degrees) && $degrees != 0){
                $new_img = imagerotate($src_img, -$degrees,imagecolorallocatealpha($src_img, 0, 0, 0, 127));

                imagedestroy($src_img);
                $src_img = $new_img;

                $deg = abs($degrees) % 180;
                $arc = ($deg > 90 ? (180 - $deg) : $deg) * M_PI / 180;
                $src_img_w = $size_w * cos($arc) + $size_h * sin($arc);
                $src_img_h = $size_w * sin($arc) + $size_h * cos($arc);

                $src_img_w -= 1;
                $src_img_h -= 1;
            }
            $this -> croppedSize(180,$data,$this->dst180,$src_img,$src_img_w,$src_img_h);
            $this -> croppedSize(50,$data,$this->dst50,$src_img,$src_img_w,$src_img_h);
            $this -> updateUser();
            $this -> croppedSize(30,$data,$this->dst30,$src_img,$src_img_w,$src_img_h);

            imagedestroy($src_img);
        }
    }

    private function croppedSize($size,$data,$dst,$src_img,$src_img_w,$src_img_h){
        $tmp_img_w = $data -> width;
        $tmp_img_h = $data -> height;
        $dst_img_w = $dst_img_h = $size;

        $src_x = $data -> x;
        $src_y = $data -> y;
        $src_w = 0;

        if ($src_x <= -$tmp_img_w || $src_x > $src_img_w) {
            $src_x = $src_w = $dst_x = $dst_w = 0;
        } else if ($src_x <= 0) {
            $dst_x = -$src_x;
            $src_x = 0;
            $src_w = $dst_w = min($src_img_w, $tmp_img_w + $src_x);
        } else if ($src_x <= $src_img_w) {
            $dst_x = 0;
            $src_w = $dst_w = min($tmp_img_w, $src_img_w - $src_x);
        }

        if ($src_w <= 0 || $src_y <= -$tmp_img_h || $src_y > $src_img_h) {
            $src_y = $src_h = $dst_y = $dst_h = 0;
        } else if ($src_y <= 0) {
            $dst_y = -$src_y;
            $src_y = 0;
            $src_h = $dst_h = min($src_img_h, $tmp_img_h + $src_y);
        } else if ($src_y <= $src_img_h) {
            $dst_y = 0;
            $src_h = $dst_h = min($tmp_img_h, $src_img_h - $src_y);
        }

        $ratio = $tmp_img_w / $dst_img_w;
        $dst_x /= $ratio;
        $dst_y /= $ratio;
        $dst_w /= $ratio;
        $dst_h /= $ratio;

        $dst_img = imagecreatetruecolor($dst_img_w, $dst_img_h);
        imagefill($dst_img, 0, 0, imagecolorallocatealpha($dst_img, 0, 0, 0, 127));
        imagesavealpha($dst_img, true);
        $result = imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
        if ($result) {
            if (!imagepng($dst_img, $dst)) {
                $this -> msg = "Failed to save the cropped image file";
            } else{

            }
        } else {
            $this -> code = 503;
            $this -> msg = "Failed to crop the image file";
        }
        imagedestroy($dst_img);
    }

    private function codeToMessage($code) {
        $errors = array(
            UPLOAD_ERR_INI_SIZE =>'The uploaded file exceeds the upload_max_filesize directive in php.ini',
            UPLOAD_ERR_FORM_SIZE =>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
            UPLOAD_ERR_PARTIAL =>'The uploaded file was only partially uploaded',
            UPLOAD_ERR_NO_FILE =>'No file was uploaded',
            UPLOAD_ERR_NO_TMP_DIR =>'Missing a temporary folder',
            UPLOAD_ERR_CANT_WRITE =>'Failed to write file to disk',
            UPLOAD_ERR_EXTENSION =>'File upload stopped by extension',
        );

        if (array_key_exists($code, $errors)) {
            return $errors[$code];
        }

        return 'Unknown upload error';
    }

    public function getResult(){
        $data = [];
        $data['middle'] = $this -> url50;
        $data['big'] = $this -> url180;
        $data['small'] = $this -> url30;
        return $data;
    }

    public function getMsg(){
        return $this -> msg;
    }

    public function getCode(){
        return $this -> code;
    }
}